import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;

public class CountWords {

    private Map<String, Integer> words = Collections.synchronizedMap(new TreeMap<String, Integer>());
    private static volatile boolean endFileFlag = false;
    private Worker[] workers;
    private static final Object sLock = new Object();
    public CountWords(String filePath, int countOfThreads) throws IOException {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(filePath));
            workers = new Worker[countOfThreads];
            String input = reader.readLine();
            for (int i = 0; i < countOfThreads; i++) {
                workers[i] = new Worker();
                workers[i].setAllWords(words);
                workers[i].setThread(new Thread(workers[i]));
                workers[i].getThread().start();

            }
            int id;
            while (input != null) {
                id = findFreeThread(countOfThreads);
                for (int i = 0; i < 10; i++) {
                    if (input == null) break;
                    workers[id].getLines().add(input);
                    input = reader.readLine();
                }
                workers[id].setRunning(true);
            }
            endFileFlag = true;
            for (int i = 0; i < countOfThreads; i++) {
                try {
                    workers[i].getThread().join();
                } catch (InterruptedException e) {

                }
            }
            System.out.printf("%-30.30s  %-30.30s%n", "Word", "Count");
            for (String word : words.keySet())
                System.out.printf("%-30.20s  %-30.20s%n", word, words.get(word));
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    public static boolean isEndFileFlag() {
        return endFileFlag;
    }

    public static void addWord(Map<String, Integer> map, String key, Integer value) {
 	synchronized(sLock) {
        if (map.containsKey(key)) {
            map.put(key, map.get(key) + value);
        } else {
            map.put(key, value);
        }
    	}
    	
    }

    public int findFreeThread(int countOfThreads) {
        int i = 0;
        while (true) {
            if (!workers[i].isRunning()) {
                return i;
            }
            i = i == countOfThreads - 1 ? 0 : i + 1;
        }
    }

    public static void main(String[] args) {
        if (args.length == 2) {
            try {
                new CountWords(args[0], Integer.valueOf(args[1]));
            } catch (IOException e) {
                System.out.println("IOException: " + e.getMessage());
            }
        } else {
            System.out.println("Usage: ");
            System.out.println("CountWords <input> <threads number>");
        }
    }
}
